package hs;
import com.google.common.collect.Maps;
import org.apache.ibatis.annotations.Select;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Dproxy {

  public static void main(String[] args) {
    UserMapper userMapper = (UserMapper)Proxy.newProxyInstance(Dproxy.class.getClassLoader(), new Class<?>[]{UserMapper.class}, new InvocationHandler() {
      @Override
      public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        Select select = method.getAnnotation(Select.class);
        Map<String, Object> methodAragsMap = buildMethodArags(method, objects);
        methodAragsMap.keySet()
          .forEach(key ->{
            System.out.println("获取方法对于的参数名及传入的值! ->   key: " + key + " ->  value: " + methodAragsMap.get(key));
          });
        if(select != null){
          String[] sql = select.value();
          String nsql = parseSql(sql[0], methodAragsMap);
          System.out.println("注解上的原sql : " + Arrays.toString(sql));
          System.out.println("解析后的sql ： " + nsql);
          System.out.println("方法返回值: " + method.getReturnType());
          System.out.println("方法泛型: " + method.getGenericReturnType());
        }
        return null;
      }
    });
    userMapper.selectAllUserById("22","sk");
  }

  private static String parseSql(String sql, Map<String, Object> methodAragsMap) {
      StringBuilder sb = new StringBuilder();
      int length = sql.length();
      for(int i = 0;i < length;i++){
        char c = sql.charAt(i);
        if(c == '#'){
          //检测格式是否正确
          int nexIndex = i + 1;
          if(sql.charAt(nexIndex) != '{'){
            throw new RuntimeException(String.format("sql格式错误,\nsql:%s\nindex:%d",sql,nexIndex));
          }
          StringBuilder  bparam = new StringBuilder();
          int pendindex = sqltoParam(sql,nexIndex,bparam);
          String param = bparam.toString();
          Object pvalue = methodAragsMap.get(param);
          if(pvalue == null){
            throw new RuntimeException(String.format("不存在sql中指定的变量值,sql=%s,变量为%s",sql,param));
          }
          sb.append(pvalue);
          i = +pendindex;
          continue;
        }
        sb.append(c);
      }
      return sb.toString();
  }

  private static int sqltoParam(String sql, int nexIndex, StringBuilder param) {
    //当前是{符号，移到变量位置
    nexIndex++;
    for (; nexIndex < sql.length(); nexIndex++) {
      char c = sql.charAt(nexIndex);
      if(c != '}'){
          param.append(c);
      }else{
        return nexIndex;
      }
    }
    throw new RuntimeException(String.format("sql异常结束，没有'{'符号,\nsql:%s",sql));
  }


  public static Map<String,Object> buildMethodArags(Method method, Object[] objects){
      HashMap<String, Object> methodAragsMap = Maps.newHashMap();
      Parameter[] parameters = method.getParameters();
      int index[] = {0};
      Arrays.asList(parameters).stream().forEach((p)->{
        methodAragsMap.put(p.getName(),objects[index[0]]);
        index[0]++;
      });
      return methodAragsMap;
    }
}

interface UserMapper{
  @Select("select * from user where id = #{id}")
  List<User> selectAllUserById(String id,String userName);
}
